package com.bytedance.improvingroad.widget

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.widget.LinearLayout
import androidx.core.view.NestedScrollingChild
import androidx.core.view.NestedScrollingChildHelper
import androidx.core.view.ViewCompat
import androidx.core.view.children

/**
 * Created by chenxiong
 * date 1/23/22
 */
class DefineNestedScrollChild @JvmOverloads constructor(
    context: Context,
    attr: AttributeSet? = null,
    style: Int = 0
) : LinearLayout(context, attr, style), NestedScrollingChild {

    private lateinit var helper: NestedScrollingChildHelper
    private var realHeight = 0

    init {
        init()
    }

    private fun init() {
        helper = NestedScrollingChildHelper(this)
        helper.isNestedScrollingEnabled = true
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        children.forEach {
            val heightSpec = MeasureSpec.makeMeasureSpec(
                MeasureSpec.getSize(heightMeasureSpec),
                MeasureSpec.UNSPECIFIED
            )
            measureChild(it, widthMeasureSpec, heightSpec)
            realHeight += it.measuredHeight
        }
        setMeasuredDimension(
            MeasureSpec.getSize(widthMeasureSpec),
            MeasureSpec.getSize(heightMeasureSpec)
        )
    }

    private var mLastTouchX = 0
    private var mLastTouchY = 0

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val consumed = IntArray(2)
        when(event.action) {
            MotionEvent.ACTION_DOWN -> {
                mLastTouchY = (event.rawY + .5f).toInt()
                var nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE
                nestedScrollAxis = nestedScrollAxis or ViewCompat.SCROLL_AXIS_HORIZONTAL
                startNestedScroll(nestedScrollAxis)
            }
            MotionEvent.ACTION_MOVE -> {
                val x = (event.rawX + .5f).toInt()
                val y = (event.rawY + .5f).toInt()
                val dx = mLastTouchX - x
                var dy = mLastTouchY - y
                mLastTouchX = x
                mLastTouchY = y

                if (dispatchNestedPreScroll(dx, dy, consumed, null)) {
                    dy -= consumed[1]
                    if (dy == 0) {
                        return true
                    }
                } else {
                    scrollBy(0, dy)
                }
            }
            MotionEvent.ACTION_CANCEL or MotionEvent.ACTION_UP -> stopNestedScroll()
        }
        return true
    }

    override fun scrollTo(x: Int, y: Int) {
        var tempY = y
        if (y < 0) {
            tempY = 0
        }
        if (y > realHeight) {
            tempY = realHeight
        }
        if (y != scrollY) {
            super.scrollTo(x, tempY)
        }
    }

    override fun setNestedScrollingEnabled(enabled: Boolean) {
        helper.isNestedScrollingEnabled = enabled
    }

    override fun isNestedScrollingEnabled(): Boolean {
        return helper.isNestedScrollingEnabled
    }

    override fun startNestedScroll(axes: Int): Boolean {
        return helper.startNestedScroll(axes)
    }

    override fun stopNestedScroll() {
        helper.stopNestedScroll()
    }

    override fun hasNestedScrollingParent(): Boolean {
        return helper.hasNestedScrollingParent()
    }

    override fun dispatchNestedScroll(
        dxConsumed: Int,
        dyConsumed: Int,
        dxUnconsumed: Int,
        dyUnconsumed: Int,
        offsetInWindow: IntArray?
    ): Boolean {
        return helper.dispatchNestedScroll(
            dxConsumed,
            dyConsumed,
            dxUnconsumed,
            dyUnconsumed,
            offsetInWindow
        )
    }

    override fun dispatchNestedPreScroll(
        dx: Int,
        dy: Int,
        consumed: IntArray?,
        offsetInWindow: IntArray?
    ): Boolean {
        return helper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
    }

    override fun dispatchNestedFling(
        velocityX: Float,
        velocityY: Float,
        consumed: Boolean
    ): Boolean {
        return helper.dispatchNestedFling(velocityX, velocityY, consumed)
    }

    override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean {
        return helper.dispatchNestedPreFling(velocityX, velocityY)
    }

}